package com.bicon.base.data.common;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.bicon.base.data.common.vo.ComboboxVo;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
public class SortUtil {
	private static Logger logger = LoggerFactory.getLogger(SortUtil.class);

	/** 
    * 给list的每个属性都指定是升序还是降序 
    *  
    * @param list 
    * @param sortnameArr  参数数组 
    * @param typeArr      每个属性对应的升降序数组， true升序，false降序 
    */  
    @Transactional(propagation=Propagation.MANDATORY)
   public static <E> void sort(List<E> list, final String[] sortnameArr, final boolean[] typeArr) {  
       if (sortnameArr.length != typeArr.length) {  
           throw new RuntimeException("属性数组元素个数和升降序数组元素个数不相等");  
       }  
       Collections.sort(list, new Comparator<E>() {  
           public int compare(E a, E b) {  
               int ret = 0;  
               try {  
                   for (int i = 0; i < sortnameArr.length; i++) {  
                       ret = compareObject(sortnameArr[i], typeArr[i], a, b);  
                       if (0 != ret) {  
                           break;  
                       }  
                   }  
               } catch (Exception e) {  
                   e.printStackTrace();  
               }  
               return ret;  
           }  
       });  
   } 
   /** 
    * 对2个对象按照指定属性名称进行排序 
    *  
    * @param sortname 
    *            属性名称 
    * @param isAsc 
    *            true升序，false降序 
    * @param a 
    * @param b 
    * @return 
    * @throws Exception 
    */  
   private static <E> int compareObject(final String sortname, final boolean isAsc, E a, E b) throws Exception {  
    //   int ret;  
       Object value1 = forceGetFieldValue(a, sortname)!=null? forceGetFieldValue(a, sortname):"";  
       Object value2 = forceGetFieldValue(b, sortname)!=null? forceGetFieldValue(b, sortname):"";  
       String str1 = value1.toString();  
       String str2 = value2.toString();  
       if (isAsc) {  
           return getEasyPinyins(str1.toString()).compareTo(getEasyPinyins(str2.toString()));

//    	   return concatPinyinStringArray(  
//                   PinyinHelper.toHanyuPinyinStringArray( ((String) str1).charAt(0))).compareTo(  
//                   concatPinyinStringArray(PinyinHelper  
//                           .toHanyuPinyinStringArray( ((String)str2).charAt(0)))); 
          // ret = str1.compareTo(str2);  
       } else {  
           return getEasyPinyins(str1.toString()).compareTo(getEasyPinyins(str2.toString()));

//    	   return concatPinyinStringArray(  
//                   PinyinHelper.toHanyuPinyinStringArray( ((String) str2).charAt(0))).compareTo(  
//                   concatPinyinStringArray(PinyinHelper  
//                           .toHanyuPinyinStringArray( ((String)str1).charAt(0)))); 
          // ret = str2.compareTo(str1);  
       }  
      // return ret;  
   }  
   /**|
    * string[]转string
    * @param pinyinArray
    * @return
    */
   private static String concatPinyinStringArray(String[] pinyinArray) {  
       StringBuffer pinyinSbf = new StringBuffer();  
       if ((pinyinArray != null) && (pinyinArray.length > 0)) {  
           for (int i = 0; i < pinyinArray.length; i++) {   
               pinyinSbf.append(pinyinArray[i]);  
           }  
       }  
       return pinyinSbf.toString();  
}
   /** 
    * 获取指定对象的指定属性值（去除private,protected的限制） 
    *  
    * @param obj 
    *            属性名称所在的对象 
    * @param fieldName 
    *            属性名称 
    * @return 
    * @throws Exception 
    */  
   public static Object forceGetFieldValue(Object obj, String fieldName){  
	    Object object = null;  
      try {
	   Field field = obj.getClass().getDeclaredField(fieldName);  
	   boolean accessible = field.isAccessible();  
       if (!accessible) {  
           // 如果是private,protected修饰的属性，需要修改为可以访问的  
           field.setAccessible(true);  
           object = field.get(obj);  
           // 还原private,protected属性的访问性质  
           field.setAccessible(accessible);  
           return object;  
       }  
       object = field.get(obj);  
       }
       catch (Exception e) {
    	   logger.debug("排序字段不存在"+obj.getClass()+"字段"+e.getMessage()+"不存在"); 
    	 //  return obj;
       }
      return object; 
   }  
   /** 
    * 汉字按照拼音排序的比较器 
    *  
    */  
   public static class PinyinComparator implements Comparator<Object> {  
       public int compare(Object o1, Object o2) {  
//           char c1 = ((String) o1).charAt(0);  
//           char c2 = ((String) o2).charAt(0);  
//           System.out.println("li3".compareTo("1zhang2") );
//           return concatPinyinStringArray(  
//                   PinyinHelper.toHanyuPinyinStringArray(c1)).compareTo(  
//                   concatPinyinStringArray(PinyinHelper  
//                           .toHanyuPinyinStringArray(c2)));  
           return getEasyPinyins(o1.toString()).compareTo(getEasyPinyins(o2.toString()));

       }  
       private String concatPinyinStringArray(String[] pinyinArray) {  
           StringBuffer pinyinSbf = new StringBuffer();  
           if ((pinyinArray != null) && (pinyinArray.length > 0)) {  
               for (int i = 0; i < pinyinArray.length; i++) {  
                   pinyinSbf.append(pinyinArray[i]);  
               }  
           }  
           return pinyinSbf.toString();  
       }  
   }  
			/** 
			* 获取包含汉字的一段文字的拼音（只获取一种情况），注意如果涉及汉字的多个读音只获取一种，不全部罗列出来 
			*/  
			public static String getEasyPinyins(String s){  
			if(s==null){  
			    s="";//防止为null，后边处理时报错  
			}  
			StringBuilder sb=new StringBuilder();  
			char[] words=s.toCharArray();//把这段文字转成字符数组  
			for(char c:words){  
			    sb.append(getPinyin(c));  
			}  
			return sb.toString();//转化成字符串返回  
			}  
			
			/** 
			* 获取一个字符的拼音(多音字则返回一种情况),非汉字则返回字符本身 
			*/  
			public static String getPinyin(char word){  
			HanyuPinyinOutputFormat pinyinFormat = new HanyuPinyinOutputFormat();   //创建拼音输入格式类  
			pinyinFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);//指定格式中的大小写属性为小写  
			pinyinFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);//指定音标格式无音标  
			pinyinFormat.setVCharType(HanyuPinyinVCharType.WITH_V);//指定用v表示ü  
			String[] formatPinyin=null;  
			try {  
			    formatPinyin = PinyinHelper.toHanyuPinyinStringArray(word, pinyinFormat);//获取对应的汉字拼音，不是汉字返回null  
			} catch (BadHanyuPinyinOutputFormatCombination e) {//会抛出异常，捕获异常  
			    //logger.error(e.getMessage());  
			    e.printStackTrace();  
			}  
			if(formatPinyin!=null){   
			    return formatPinyin[0];//返回读音,如果多音字自返回一个  
			}else{  
			    return String.valueOf(word);//非汉字则返回字符本身  
			}  
			}  
   public static void main(String[] args) {
	    String[] arr = { "张三", "李五", "王五", "赵六", "JAVA", "123", "$%$#", "哈哈A",  
	            "1哈哈A", "1哈哈b", "1哈哈a", "李四", "哈", "怡情" };  
	    String [] sortNameArr = {"text1"};  
	    String str="我是一个粉刷匠,粉刷benling强1";
	    ComboboxVo c=new ComboboxVo();
	    c.setId("1");
	    c.setText("");
	    ComboboxVo c1=new ComboboxVo();
	    c1.setId("1");
	    c1.setText(null);
	    List<ComboboxVo> list=new ArrayList<ComboboxVo>();
	    list.add(c);
	    list.add(c1);
        boolean [] isAscArr = {false}; 
      sort(list,sortNameArr,isAscArr); 
	   // List<String> list = Arrays.asList(arr);  
	    Arrays.sort(arr,new PinyinComparator());  
	    System.out.println(list);  
	    System.out.println(getEasyPinyins(str));
}
}
